/*-------------------------------------------------------------------------
 *
 * fsmfuncs.c
 *	  调查 FSM 页的函数
 *
 * 这些函数对超级用户是受限的，因为如果输入检查不够严格，可能会引入安全漏洞。
 * 您需要是超级用户才能获取原始页面图像，因此几乎没有使用这些函数而不具备超级用户权限的用例。
 *
 * Copyright (c) 2007-2022, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *	  contrib/pageinspect/fsmfuncs.c
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "funcapi.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "pageinspect.h"
#include "storage/fsm_internals.h"
#include "utils/builtins.h"

/*
 * 转储FSM页面的内容。
 */
PG_FUNCTION_INFO_V1(fsm_page_contents);

Datum fsm_page_contents(PG_FUNCTION_ARGS)
{
	bytea	   *fc_raw_page = PG_GETARG_BYTEA_P(0);
	StringInfoData fc_sinfo;
	Page		fc_page;
	FSMPage		fc_fsmpage;
	int			fc_i;

	if (!superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 errmsg("must be superuser to use raw page functions")));

	fc_page = get_page_from_raw(fc_raw_page);

	if (PageIsNew(fc_page))
		PG_RETURN_NULL();

	fc_fsmpage = (FSMPage) PageGetContents(fc_page);

	initStringInfo(&fc_sinfo);

	for (fc_i = 0; fc_i < NodesPerPage; fc_i++)
	{
		if (fc_fsmpage->fp_nodes[fc_i] != 0)
			appendStringInfo(&fc_sinfo, "%d: %d\n", fc_i, fc_fsmpage->fp_nodes[fc_i]);
	}
	appendStringInfo(&fc_sinfo, "fp_next_slot: %d\n", fc_fsmpage->fp_next_slot);

	PG_RETURN_TEXT_P(cstring_to_text_with_len(fc_sinfo.data, fc_sinfo.len));
}
